feat(sync): add sync_include_cwd_prefixes ingestion filter - #1004
Conversation
Add an opt-in config option that restricts local session ingestion to sessions whose working directory lives under one of the configured path prefixes. The filter is enforced as a veto in prepareSessionWrite so every full-write path across all agents is covered uniformly. Sessions without a recorded cwd are skipped while the filter is set; remote-host sync is unaffected because the prefixes describe local paths. The filter gates ingestion only: sessions already in the archive are preserved, consistent with the persistent-archive policy.
roborev: Combined Review (
|
tryIncrementalJSONL now falls back to a full parse for sessions whose stored cwd is outside the allow-list, so prepareSessionWrite applies the same veto, and writeIncremental refuses filtered updates as a seam guard for any future producer. Adds a regression test for an archived outside-prefix session receiving appended messages.
|
Addressed the roborev medium finding in 368b2c7:
|
roborev: Combined Review (
|
|
looking |
A full resync where sync_include_cwd_prefixes vetoes every discovered session previously ended with Synced == 0, Failed == 0, and no parser-excluded marker, so the resync abort guard read the run as an unsafe empty rebuild, aborted the swap, and left NeedsResync true on every startup. prepareSessionWrite now returns a verdict that distinguishes the cwd allow-list veto from archive-preserve vetoes, the write batch paths count filtered sessions into sync stats, and the abort guard treats an all-filtered run as intentional so the swap proceeds and the orphan copy restores the archived rows.
roborev: Combined Review (
|
…c-include-cwd-prefixes * origin/main: feat(usage): show session context and token breakdown (kenn-io#982) (kenn-io#989) perf(push): ignore volatile stat fields for session candidacy (kenn-io#1014) feat(settings): support worktree layout mappings (kenn-io#582) (kenn-io#993) fix(config): apply port from config.toml to Config struct (kenn-io#1005) feat(parser): add Qoder session support (kenn-io#1013) fix(usage): wire agent exclusions through usage filters (kenn-io#972) fix(frontend): preserve calendar range picker selections (kenn-io#1016) feat: semantic search with run-grouped embeddings and conversation-unit citations (kenn-io#999) feat(parser): add ZCode SQLite sync support (kenn-io#1003) (kenn-io#1012) fix(sync): drop unchanged opencode-family container sessions (kenn-io#1015) fix(sync): skip local git discovery for foreign-machine sessions (kenn-io#1008) fix(activity): count subagent sessions in activity report cost (kenn-io#1006) feat(i18n): add Korean (ko) locale support (kenn-io#1002)
Merging main brought in the Qoder parser, whose test helper still called writeBatch with three return values. Discard the new cwd-filtered count like the other test call sites.
roborev: Combined Review (
|
The cwd allow-list compared raw strings and treated both slash and backslash as path boundaries on every platform. A recorded cwd such as /home/me/work/../client-b, or a POSIX directory literally named "work\client-b", could match a /home/me/work prefix while living outside it. Clean prefixes and cwds with filepath.Clean before matching and use os.PathSeparator as the only boundary, so .. components resolve lexically and a backslash is an ordinary filename character on POSIX. A root prefix now matches instead of being silently dropped. Document the matching semantics in docs/configuration.md.
roborev: Combined Review (
|
…d filter Two review findings on the cwd allow-list: Parser exclusions (including engine stale-row cleanup) ran before the cwd veto, so a source outside the allow-list could hard-delete an archived row while its replacement write was vetoed, and the excluded ID also skipped resync's orphan copy. Both delete seams now require the source to prove at least one allowed session or incremental update; otherwise its exclusions are dropped and archived rows survive, matching the documented ingestion-only contract. The resync abort guard's cwd-filtered escape fired when any session was filtered, which could excuse mixed zero-write runs. collectAndBatch now drops vetoed sessions before batching and counts fully filtered files, and the escape additionally requires every OK file to be accounted for as cwd-filtered or parser-excluded. The guard moved into shouldAbortResyncSwap so its branches are unit-testable.
roborev: Combined Review (
|
|
Makes sense. Merging |
Adds an opt-in
sync_include_cwd_prefixesconfig option that restricts local session ingestion to sessions whose working directory lives under one of the configured path prefixes.Motivation: on a machine shared across multiple clients or workspaces, the archive currently indexes every session it can find, so transcripts from unrelated (possibly confidential) workspaces end up side by side in one database and UI. The DuckDB/PG mirror
projectsfilters can carve out a scoped read-only view, but that requires a second serving process and an exact project-name list that goes stale as projects are added. A cwd allow-list at ingestion solves this at the source, works uniformly across agents (including agents like Codex whose session files are date-organized rather than per-project), and keeps everything in the normalserveflow.What changed
internal/sync/cwd_filter.go(new):cwdPrefixFilterwith normalization (trim, drop blanks, strip trailing separators) and path-boundary-aware matching (/a/bmatches/a/b/cbut not/a/bc; both/and\boundaries).internal/sync/engine.go:EngineConfig.IncludeCwdPrefixes; the filter is enforced as a veto inprepareSessionWrite, before the preserve/merge handling, so every full-write path across all agents is covered by the existing central seam. Callers already treat the veto as an intentional skip.internal/config/config.go:SyncIncludeCwdPrefixes(toml:"sync_include_cwd_prefixes", config-file only, not exposed via the settings API).cmd/agentsview/*.go,internal/server/huma_routes_sync.go: the option is wired into every local engine construction site. The remote-sync engine (internal/remotesync) is deliberately left unwired — the prefixes describe local paths, so applying them to remote hosts' cwds would silently drop remote sessions.cmd/agentsview/cli.go:--helpsection documenting the option.docs/configuration.md: new "Restricting Ingestion by Working Directory" section under Sync Behavior.cwd_filter_test.go), config load tests, and an engine integration test (cwd_filter_integration_test.go) syncing one in-prefix, one out-of-prefix, and one boundary-sibling (/Users/alice/workspacevs prefix/Users/alice/work) Claude session.Semantics / decisions
--help.AGENTS.md; the docs point atagentsview prunefor cleaning up previously ingested sessions.~is not expanded (documented).Where to look
The veto placement in
prepareSessionWriteis the main review surface — it sits after the worktree-project resolution and beforeshouldPreserveOpenCodeFormatArchive, so a filtered session is never written by any downstream path. The other question worth a look is the empty-cwd decision; happy to flip it to allow-when-missing if you'd rather bias toward completeness.